﻿namespace Beetle.Clients
{
    using Beetle;
    using Smark.Core;
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Text;

    public class TcpSyncChannel<T> : ITcpSyncChannel where T: Beetle.Package, new()
    {
        private bool _field_a;
        private bool _field_b;
        private BufferWriter _field_c;
        private byte[] _field_d;
        private object _field_e;
        private Beetle.Package _field_f;
        private KeyValueCollection<object> _field_g;
        private int _field_h;
        [CompilerGenerated]
        private System.Net.Sockets.Socket _field_i;
        [CompilerGenerated]
        private int _field_j;
        [CompilerGenerated]
        private Encoding _field_k;

        public TcpSyncChannel()
        {
            this._field_d = new byte[0x2000];
            this._field_g = new KeyValueCollection<object>();
            this.Timeout = 0x2710;
            this.Coding = Encoding.UTF8;
        }

        private void a()
        {
            try
            {
                int tickCount = Environment.TickCount;
                while (this._field_e == null)
                {
                    if ((Environment.TickCount - tickCount) > this.Timeout)
                    {
                        throw NetTcpException.ClientReceiveTimeout();
                    }
                    int count = this.Socket.Receive(this._field_d);
                    if (count == 0)
                    {
                        throw NetTcpException.ClientIsDisposed();
                    }
                    this._field_f.Import(this._field_d, 0, count);
                }
            }
            catch (NetTcpException exception)
            {
                this.Dispose();
                throw exception;
            }
            catch (Exception exception2)
            {
                this.Dispose();
                throw NetTcpException.ClientDataProcessError(exception2);
            }
        }

        private void a(BufferWriter A_0)
        {
            try
            {
                int offset = 0;
                this._field_h = 0;
                while (this._field_c._field_b.Count > 0)
                {
                    using (Class_b _b = this._field_c._field_b.Dequeue())
                    {
                        offset = 0;
                        while (offset < _b._field_h)
                        {
                            int num2 = this.Socket.Send(_b._field_e, offset, _b._field_h - offset, SocketFlags.None);
                            if (num2 == 0)
                            {
                                throw NetTcpException.ClientIsDisposed();
                            }
                            offset += num2;
                            this._field_h += num2;
                        }
                        continue;
                    }
                }
            }
            catch (Exception exception)
            {
                this.Dispose();
                throw NetTcpException.ClientDataProcessError(exception);
            }
        }

        private void a(PacketRecieveMessagerArgs A_0)
        {
            this._field_e = A_0.Message;
        }

        public void Connect(string host, int port)
        {
            if (!this._field_b)
            {
                if (!TcpUtils._field_a)
                {
                    throw NetTcpException.NotInitialize();
                }
                if (this._field_a)
                {
                    throw NetTcpException.ClientIsDisposed();
                }
                IPAddress[] hostAddresses = Dns.GetHostAddresses(host);
                this.Socket=(new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp));
                this.Socket.Connect(new IPEndPoint(hostAddresses[0], port));
                this.Socket.ReceiveTimeout = this.Timeout;
                this.Socket.SendTimeout = this.Timeout;
                this.OnInit();
                this._field_b = true;
                TcpServer.SetKeepAliveValues(this.Socket, 0x4e20, 0x2710);
            }
        }

        public void Dispose()
        {
            lock (((TcpSyncChannel<T>) this))
            {
                if (!this._field_a)
                {
                    this._field_a = true;
                    this.OnDisposed();
                }
            }
        }

        protected virtual void OnDisposed()
        {
            if (this._field_f != null)
            {
                this._field_f.Dispose();
            }
            TcpServer.ReleaseSocket(this.Socket);
        }

        protected virtual void OnInit()
        {
            this._field_f = Activator.CreateInstance<T>();
            this._field_f.GetPools();
            this._field_f.CreateWriterReader();
            this._field_f.ReceiveMessage = new EventPacketRecievMessage(this.a);
            this._field_c = new BufferWriter(this.Coding, true, false);
        }

        protected object OnSend(IMessage data)
        {
            if (!this.Connected)
            {
                throw NetTcpException.ClientMustBeConnected();
            }
            if (this._field_a)
            {
                throw NetTcpException.ClientIsDisposed();
            }
            this._field_e = null;
            this._field_c.Reset();
            this._field_f.MessageWrite(data, this._field_c);
            this.a(this._field_c);
            this.a();
            return this._field_e;
        }

        public virtual object Send(object data)
        {
            return this.OnSend((IMessage) this.Package.WriteCast(data));
        }

        public T1 Send<T1>(object data)
        {
            return (T1) this.Send(data);
        }

        public Encoding Coding
        {
            [CompilerGenerated]
            get
            {
                return this._field_k;
            }
            [CompilerGenerated]
            set
            {
                this._field_k = value;
            }
        }

        public bool Connected
        {
            get
            {
                return this._field_b;
            }
        }

        public bool IsDisplsed
        {
            get
            {
                return this._field_a;
            }
        }

        public object this[string name]
        {
            get
            {
                return this._field_g[name];
            }
            set
            {
                this._field_g[name] = value;
            }
        }

        public Beetle.Package Package
        {
            get
            {
                return this._field_f;
            }
        }

        public KeyValueCollection<object> Properties
        {
            get
            {
                return this._field_g;
            }
        }

        public System.Net.Sockets.Socket Socket
        {
            [CompilerGenerated]
            get
            {
                return this._field_i;
            }
            [CompilerGenerated]
            private set
            {
                this._field_i = value;
            }
        }

        public int Timeout
        {
            [CompilerGenerated]
            get
            {
                return this._field_j;
            }
            [CompilerGenerated]
            set
            {
                this._field_j = value;
            }
        }
    }
}

